package com.sixth.core.aspect;

import com.sixth.core.annotation.OperaLog;
import com.sixth.core.entity.OperLog;
import com.sixth.core.entity.User;
import com.sixth.core.feign.UserFeign;
import com.sixth.core.util.WebUtil;
import com.sixth.core.vo.R;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

/**
 * 操作日志切面
 * 用于拦截被 @OperaLog 注解标记的方法，记录操作日志
 */
@Aspect
@Component
public class OperaLogAspect {
    @Autowired
    private UserFeign userFeign;

    /**
     * 定义切点，匹配所有被 @OperaLog 注解的方法
     */
    @Pointcut("@annotation(com.sixth.core.annotation.OperaLog)")
    public void pointcut() {
    }

    /**
     * 环绕通知，用于处理切点方法的前置和后置逻辑
     *
     * @param joinPoint 切入点对象，用于获取方法信息和参数
     * @return 方法执行结果
     * @throws Throwable 方法执行可能抛出的异常
     */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        OperaLog annotation = method.getAnnotation(OperaLog.class);
        OperLog operLog = new OperLog();
        HttpServletRequest request = WebUtil.getRequest();
        operLog.setTitle(annotation.value()); // 设置操作日志标题
        operLog.setBusinessType(annotation.type()+""); // 设置业务类型
        operLog.setMethod(method.getName()); // 设置方法名
        operLog.setRequestMethod(request.getMethod()); // 设置请求方法类型
        String usernameTelephone = WebUtil.getUsername(); // 获取用户名或电话
        R<User> userR = userFeign.getByPhone(usernameTelephone); // 通过电话获取用户信息
        String username = userR.getData().getUserName();
        operLog.setOperName(username); // 设置操作人姓名
        operLog.setOperUrl(request.getRequestURL().toString()); // 设置请求URL
        operLog.setOperIp(request.getRemoteAddr()); // 设置操作IP地址
        operLog.setOperLocation("内网IP"); // 设置操作地点（默认内网IP）
        operLog.setOperParam(Arrays.toString(joinPoint.getArgs())); // 设置操作参数
        operLog.setOperTime(new Date()); // 设置操作时间

        try {
            Object proceed = joinPoint.proceed(); // 执行原方法
            operLog.setJsonResult(proceed.toString()); // 设置返回结果
            operLog.setStatus("0"); // 设置操作状态为成功
            operLog.setErrorMsg(""); // 清空错误信息
            return proceed;
        } catch (Exception e) {
            operLog.setJsonResult(""); // 操作失败时，返回结果置空
            operLog.setErrorMsg(e.getMessage()); // 设置错误信息
            operLog.setStatus("1"); // 设置操作状态为失败
        } finally {
            System.out.println(operLog); // 输出日志信息
            userFeign.save(operLog); // 保存操作日志
            System.out.println("=============================="); // 分隔符
        }
        return null;
    }
}
